ostree-prepare-root: Refactor: Create /sysroot.tmp much later
authorWilliam Manley <will@williammanley.net>
Mon, 18 Jul 2016 17:02:12 +0000 (18:02 +0100)
committerAtomic Bot <atomic-devel@projectatomic.io>
Tue, 2 Aug 2016 19:07:25 +0000 (19:07 +0000)
Typically we have our ready made-up up root at
`/sysroot/ostree/deploy/.../` (`deploy_path`) and the real rootfs at
`/sysroot` (`root_mountpoint`).  We want to end up with our made-up root
at `/sysroot/` and the real rootfs under `/sysroot/sysroot` as systemd
will be responsible for moving `/sysroot` to `/`.

We need to do this in 3 moves to avoid trying to move `/sysroot` under
itself:

1. `/sysroot/ostree/deploy/...` -> `/sysroot.tmp`
2. `/sysroot` -> `/sysroot.tmp/sysroot`
3. `/sysroot.tmp` -> `/sysroot`

This is a refactoring to group all these operations together so I can
implement an alternative in terms of `pivot_root`.

Closes: #403
Approved by: cgwalters

src/switchroot/ostree-prepare-root.c

index 77a084ade03b14b65bd2002a829926829c436339..114bd6722c5ce096748f6805f22bdad0e097bd79 100644 (file)
@@ -191,7 +191,6 @@ main(int argc, char *argv[])
   char *deploy_path = NULL;
   char srcpath[PATH_MAX];
   char destpath[PATH_MAX];
-  char newroot[PATH_MAX];
   struct stat stbuf;
   int orig_cwd_dfd;
 
@@ -202,16 +201,6 @@ main(int argc, char *argv[])
 
   deploy_path = resolve_deploy_path (root_mountpoint);
 
-  /* Create a temporary target for our mounts in the initramfs; this will
-   * be moved to the new system root below.
-   */
-  snprintf (newroot, sizeof(newroot), "%s.tmp", root_mountpoint);
-  if (mkdir (newroot, 0755) < 0)
-    {
-      perrorv ("Couldn't create temporary sysroot '%s': ", newroot);
-      exit (EXIT_FAILURE);
-    }
-  
   /* Work-around for a kernel bug: for some reason the kernel
    * refuses switching root if any file systems are mounted
    * MS_SHARED. Hence remount them MS_PRIVATE here as a
@@ -225,7 +214,7 @@ main(int argc, char *argv[])
     }
 
   /* Make deploy_path a bind mount, so we can move it later */
-  if (mount (deploy_path, newroot, NULL, MS_BIND, NULL) < 0)
+  if (mount (deploy_path, deploy_path, NULL, MS_BIND, NULL) < 0)
     {
       perrorv ("failed to initial bind mount %s", deploy_path);
       exit (EXIT_FAILURE);
@@ -233,7 +222,7 @@ main(int argc, char *argv[])
 
   /* Link to the deployment's /var */
   snprintf (srcpath, sizeof(srcpath), "%s/../../var", deploy_path);
-  snprintf (destpath, sizeof(destpath), "%s/var", newroot);
+  snprintf (destpath, sizeof(destpath), "%s/var", deploy_path);
   if (mount (srcpath, destpath, NULL, MS_MGC_VAL|MS_BIND, NULL) < 0)
     {
       perrorv ("failed to bind mount %s to %s", srcpath, destpath);
@@ -245,7 +234,7 @@ main(int argc, char *argv[])
   snprintf (srcpath, sizeof(srcpath), "%s/boot/loader", root_mountpoint);
   if (lstat (srcpath, &stbuf) == 0 && S_ISLNK (stbuf.st_mode))
     {
-      snprintf (destpath, sizeof(destpath), "%s/boot", newroot);
+      snprintf (destpath, sizeof(destpath), "%s/boot", deploy_path);
       if (lstat (destpath, &stbuf) == 0 && S_ISDIR (stbuf.st_mode))
         {
           snprintf (srcpath, sizeof(srcpath), "%s/boot", root_mountpoint);
@@ -257,7 +246,7 @@ main(int argc, char *argv[])
         }
     }
 
-  /* Here we do a dance to chdir to the newroot so that we can have
+  /* Here we do a dance to chdir to the deploy_path so that we can have
    * the potential overlayfs mount points not look ugly.  However...I
    * think we could do this a lot earlier and make all of the mounts
    * here just be relative.
@@ -269,9 +258,9 @@ main(int argc, char *argv[])
       exit (EXIT_FAILURE);
     }
 
-  if (chdir (newroot) < 0)
+  if (chdir (deploy_path) < 0)
     {
-      perrorv ("failed to chdir to newroot");
+      perrorv ("failed to chdir to deploy_path");
       exit (EXIT_FAILURE);
     }
 
@@ -324,19 +313,39 @@ main(int argc, char *argv[])
 
   touch_run_ostree ();
 
-  /* Move physical root to $deployment/sysroot */
-  snprintf (destpath, sizeof(destpath), "%s/sysroot", newroot);
-  if (mount (root_mountpoint, destpath, NULL, MS_MOVE, NULL) < 0)
+  /* In this instance typically we have our ready made-up up root at
+   * /sysroot/ostree/deploy/.../ (deploy_path) and the real rootfs at
+   * /sysroot (root_mountpoint).  We want to end up with our made-up root at
+   * /sysroot/ and the real rootfs under /sysroot/sysroot as systemd will be
+   * responsible for moving /sysroot to /.
+   *
+   * We need to do this in 3 moves to avoid trying to move /sysroot under
+   * itself:
+   *
+   * 1. /sysroot/ostree/deploy/... -> /sysroot.tmp
+   * 2. /sysroot -> /sysroot.tmp/sysroot
+   * 3. /sysroot.tmp -> /sysroot
+   */
+  if (mkdir ("/sysroot.tmp", 0755) < 0)
     {
-      perrorv ("Failed to MS_MOVE %s to '%s'", root_mountpoint, destpath);
+      perrorv ("couldn't create temporary sysroot /sysroot.tmp: ");
       exit (EXIT_FAILURE);
     }
 
-  /* Now that we've set up all the bind mounts in /sysroot.tmp which
-   * points to the deployment, move it /sysroot.  From there,
-   * systemd's initrd-switch-root.target will take over.
-   */
-  if (mount (newroot, root_mountpoint, NULL, MS_MOVE, NULL) < 0)
+  if (mount (deploy_path, "/sysroot.tmp", NULL, MS_MOVE, NULL) < 0)
+    {
+      perrorv ("failed to MS_MOVE '%s' to '/sysroot.tmp'", deploy_path);
+      exit (EXIT_FAILURE);
+    }
+
+  if (mount (root_mountpoint, "/sysroot.tmp/sysroot", NULL, MS_MOVE, NULL) < 0)
+    {
+      perrorv ("failed to MS_MOVE '%s' to '/sysroot.tmp/sysroot'",
+          root_mountpoint);
+      exit (EXIT_FAILURE);
+    }
+
+  if (mount ("/sysroot.tmp", root_mountpoint, NULL, MS_MOVE, NULL) < 0)
     {
       perrorv ("failed to MS_MOVE %s to %s", deploy_path, root_mountpoint);
       exit (EXIT_FAILURE);